import React from 'react';

import "./../../../pages/amap/icon/css/icon.less";

const optsDetails = ['gridSize', 'minClusterSize', 'maxZoom', 'averageCenter', 'styles', 'renderCluserMarker', 'zoomOnClick'];

export default class MarkerClusterer extends React.Component {
  constructor(props) {
    super(props);
    if (typeof window !== 'undefined') {
      if (!props.__map__) {
        throw new Error('MarkerClusterer has to be a child of Map component');
      } else {

        let t = this;
        t.map = props.__map__;
      }
    }
  }

  componentWillReceiveProps(nextProps) {
    const currentProps = this.props;

    this.resolveMarkerClusterer(currentProps).then((data) => {
      this.refreshMarkerClusterer(nextProps, currentProps);
    })
  }

  shouldComponentUpdate(nextProps, nextState) {
    const thisProps = this.props || {},
      thisState = this.state || {};

    for (const key in nextProps) {
      if (thisProps[key] !== nextProps[key]) {
        return true;
      }
    }

    for (const key in nextState) {
      if (thisState[key] !== nextState[key]) {
        return true;
      }
    }
    return false;
  }

  resolveMarkerClusterer(props) {
    let t = this;
    if (t.clusterer) {
      return new Promise((resolve) => {
        resolve(t.clusterer);
      });
    } else {
      return new Promise((resolve) => {
        t.map.plugin(['AMap.MarkerClusterer'], () => {
          const clustererOptions = t.buildInitOptions(props);
          t.clusterer = new window.AMap.MarkerClusterer(t.map, clustererOptions.markers, clustererOptions.opts);
          resolve(t.clusterer);
        });
      });
    }
  }

  buildInitOptions(props) {
    let t = this;
    const options = {
      opts: {},
      markers: []
    };
    optsDetails.forEach((key) => {
      if (key in props) {
        options.opts[key] = props[key];
      }
    });

    if ('markers' in props) {
      props.markers.forEach((marker) => {
        options.markers.push(t.createMarker(marker));
      })
    }

    return options;
  }

  refreshMarkerClusterer(nextProps, currentProps) {
    let t = this;
    optsDetails.forEach((key) => {
      if (nextProps[key] !== currentProps[key]) {
        switch (key) {
          case 'gridSize':
            t.clusterer.setGridSize(nextProps[key]);
            break;
          case 'minClusterSize':
            t.clusterer.setMinClusterSize(nextProps[key]);
            break;
          case 'maxZoom':
            t.clusterer.setMaxZoom(nextProps[key]);
            break;
          case 'averageCenter':
            t.clusterer.setAverageCenter(nextProps[key]);
            break;
          case 'styles':
            t.clusterer.setStyles(nextProps[key]);
            break;
          default:
            break;
        }
      }
    });

    if (nextProps.markers !== currentProps.markers) {
      let markers = [];
      nextProps.markers.forEach((marker) => {
        markers.push(t.createMarker(marker))
      });
      t.clusterer.setMarkers(markers);
    }
  }

  componentWillUnmount() {
    this.clusterer.setMap(null);
    delete this.clusterer;
  }

  createMarker(marker) {
    let t = this;
    let markerObj = new AMap.Marker(t.editMarkerOptions(marker));
    markerObj.on('click', () => {
      t.props.markerClick({markerType: marker.customOpts.markerType, markerId: marker.customOpts.markerId});
    });
    return markerObj;
  }

  editMarkerOptions(marker) {
    return {
      position: new AMap.LngLat(marker.opts.position.longitude,marker.opts.position.latitude),
      content: marker.opts.content,
      offset: new AMap.Pixel(marker.opts.offset.x, marker.opts.offset.y),
      animation: marker.opts.animation,
      visible: marker.opts.visible,
      title: marker.opts.title,
      draggable: marker.opts.draggable,
      topWhenClick: marker.opts.topWhenClick,
      extData: marker.opts.extData
    };
  }

  render() {
    return <div>Empty</div>;
  }

}

MarkerClusterer.contextTypes = {
  router: React.PropTypes.isRequired
};
